package com.ai.service.made.impl;

import com.ai.common.CommonResponse;
import com.ai.entity.alarm.RecordAlarmPO;
import com.ai.entity.made.RegionBase;
import com.ai.entity.made.RegionManage;
import com.ai.entity.made.camera.CameraPO;
import com.ai.mapper.alarm.RecordAlarmMapper;
import com.ai.mapper.made.RegionManageMapper;
import com.ai.model.made.CameraStatisticsDto;
import com.ai.model.made.RegionalViolationDto;
import com.ai.model.made.TopFiveViolationsDto;
import com.ai.model.param.RegionStaticsViolationParam;
import com.ai.service.made.CameraService;
import com.ai.service.made.IRegionBaseService;
import com.ai.service.made.IRegionManageService;
import com.ai.service.made.RecordAlarmService;
import com.ai.util.SecurityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jcuda.driver.CUdevice;
import jcuda.driver.JCudaDriver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

//import static com.sun.deploy.util.BufferUtil.GB;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jiaok
 * @since 2023-07-24
 */
@Service
@Slf4j
public class RegionManageServiceImpl extends ServiceImpl<RegionManageMapper, RegionManage> implements IRegionManageService {


    @Resource
    private CameraService cameraService;
    @Resource
    RecordAlarmMapper recordAlarmMapper;

    @Resource
    private RecordAlarmService recordAlarmService;


    @Resource
    private IRegionBaseService iRegionBaseService;

    /**
     * 获取当前的所有区域列表
     * @return
     */
    @Override
    public CommonResponse getList() {
        List<RegionManage> regionManageList = list();

        return CommonResponse.ok(regionManageList);
    }

    /**
     * 获取当前区域管理的所有摄像头
     * @param id 区域id
     * @return 返回所绑定的摄像头code
     */
    @Override
    public CommonResponse getBindList(String id) {
        List<RegionManage> regionManages = list(new QueryWrapper<RegionManage>().eq("region_id", id));

        ArrayList<String> cameraCode = new ArrayList<>();
        if (!CollectionUtils.isEmpty(regionManages)){
            //如果含有摄像头,获取所有摄像头的code
            List<String> stringList = regionManages.stream().map(regionManage -> {
                CameraPO cameraPO = cameraService.getById(regionManage.getCameraId());
                return cameraPO.getCode();
            }).collect(Collectors.toList());
            cameraCode.addAll(stringList);
        }

        return CommonResponse.ok(cameraCode);
    }

    /**
     * 区域绑定摄像头信息
     * @param id
     * @param cameraIds
     * @return
     */
    @Override
    @Transactional
    public CommonResponse manageCamera(String id, List<String> cameraIds) {

        /**
         * 如果摄像头ids为空，则说明当前操作为解绑所有摄像头信息
         */
        if (CollectionUtils.isEmpty(cameraIds)){
            log.info("===========================  清空当前区域所绑定的摄像头  ===========================");
            //首先删除当前区域的绑定信息
            boolean regionIdRemove = this.remove(new QueryWrapper<RegionManage>().eq("region_id", id));
            //没有新绑定关系，全部删除即可
            return CommonResponse.ok();
        }

        //获取当前区域内之前已经绑定的摄像头信息
        QueryWrapper<RegionManage> wrapper = new QueryWrapper<>();
        wrapper.eq("region_id",id);
        List<RegionManage> regionManageList = this.list(wrapper);
        List<String> dbCameraIds = regionManageList.stream().map(RegionManage::getCameraId).collect(Collectors.toList());
        cameraIds.removeAll(dbCameraIds);//两个集合取差集

        if (CollectionUtils.isEmpty(cameraIds) ){
            log.info("=========================== 区域无需新绑定摄像头  ===========================");
            //无需对原有关系进行修改
            return CommonResponse.ok("信息更新成功");
        }

        //查看当前摄像头是否被其他区域绑定，如果被其他区域绑定，则直接删除，将当前摄像头绑定到当前的区域中
        QueryWrapper<RegionManage> cameraBindOtherRegionWrapper = new QueryWrapper<>();
        cameraBindOtherRegionWrapper.in("camera_id",cameraIds);
        List<RegionManage> otherBindRelationList = this.list(cameraBindOtherRegionWrapper);
        if (!CollectionUtils.isEmpty(otherBindRelationList)){
            List<Integer> regionIds = otherBindRelationList.stream().map(RegionManage::getId).collect(Collectors.toList());
            log.info("===========================  摄像头被其他区域所绑定  ===========================");
            log.info("===========================  与其他区域进行解绑操作 ===========================");
            boolean removeBatchByIds = removeBatchByIds(regionIds);
        }


        //新建绑定关系
        ArrayList<RegionManage> regionManages = new ArrayList<>();

        LocalDateTime dateTime = LocalDateTime.now();//创建时间
        String loginUserName = SecurityUtils.getLoginUserName();


        for (String cameraId : cameraIds) {
            RegionManage regionManage = new RegionManage();
            regionManage.setRegionId(id);
            regionManage.setCreateTime(dateTime);
            regionManage.setUpdateTime(dateTime);
            regionManage.setCreateUser(loginUserName);
            regionManage.setUpdateUser(loginUserName);
            regionManage.setCameraId(cameraId);
            regionManages.add(regionManage);
        }
        boolean b = this.saveBatch(regionManages);
        if (!b){
            throw new RuntimeException("信息更新失败");
        }
        return CommonResponse.ok("信息更新成功");
    }

    /**
     * 获取当前区域管理的所有摄像头
     * @param id 区域id
     * @return 返回所绑定的摄像头id
     */
    @Override
    public CommonResponse getBindListID(String id) {
        List<RegionManage> regionManages = list(new QueryWrapper<RegionManage>().eq("region_id", id));

        ArrayList<Integer> cameraCode = new ArrayList<>();
        if (!CollectionUtils.isEmpty(regionManages)){
            //如果含有摄像头,获取所有摄像头的code
            List<Integer> stringList = regionManages.stream().map(regionManage -> {
                CameraPO cameraPO = cameraService.getById(regionManage.getCameraId());
                return cameraPO.getId();
            }).collect(Collectors.toList());
            cameraCode.addAll(stringList);
        }

        return CommonResponse.ok(cameraCode);
    }

    /**
     * 获取所有区域信息
     * @return
     */
    @Override
    public CommonResponse getRegionList() {
        List<RegionManage> list = this.list();
        CommonResponse<List<RegionManage>> response = CommonResponse.ok(list);
        return response;
    }

    /**
     * 统计指定区域的月违规、年度违规
     * @param regionStaticsViolationParam
     * @return
     */
    @Override
    public CommonResponse statisticsViolation(RegionStaticsViolationParam regionStaticsViolationParam) {

        //获取当前年份
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        int lastYear= currentYear-1;
        int beforeLastYear =currentYear-2;
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        HashMap<String, List<Integer>> statisticsRes = new HashMap<>();
        List<Integer> monthStatistics = new ArrayList<>();//当年月违规统计
        List<Integer> yearStatistics = new ArrayList<>();//近三年违规统计
        //获取当前区域内的所有摄像头

        CommonResponse bindList = getBindList(regionStaticsViolationParam.getRegionId());
        ArrayList<String> cameraCode = (ArrayList<String>) bindList.getData();

        if (CollectionUtils.isEmpty(cameraCode)){
            //说明当前区域内没有摄像头，直接返回默认值0即可
            int [] initMonthStatics ={0,0,0,0,0,0,0,0,0,0,0,0};
            monthStatistics = Arrays.stream(initMonthStatics).boxed().collect(Collectors.toList());
            yearStatistics.add(0);
            yearStatistics.add(0);
            yearStatistics.add(0);

        }else {
            //获取当前所有摄像头对应的功能记录
            List<RecordAlarmPO> recordList=  recordAlarmService.getRecordByCameraCodeAndFunType(cameraCode,regionStaticsViolationParam.getFunType());

            if (CollectionUtils.isEmpty(recordList)){
                //当前区域没有对应的违规记录
                for (int i = 0; i < 12; i++) {
                    monthStatistics.add(0);
                }
                for (int i = 0; i < 3; i++) {
                    yearStatistics.add(0);
                }
            }else {
                //有对应的记录，  进行统计分析
                //取出所有的年份信息
                List<String> dateStrList = recordList.stream().map(recordAlarmPO -> simpleDateFormat.format(recordAlarmPO.getCreateTime())).collect(Collectors.toList());
                List<LocalDateTime> allRecordDateTimes = dateStrList.stream().map(dateStr -> LocalDateTime.parse(dateStr, formatter)).collect(Collectors.toList());

                //统计年度违约数量
                Integer currentCount = Math.toIntExact(allRecordDateTimes.stream().filter(date -> date.getYear() == currentYear).count());
                Integer lastCount = Math.toIntExact(allRecordDateTimes.stream().filter(date -> date.getYear() == lastYear).count());
                Integer beforeCount = Math.toIntExact(allRecordDateTimes.stream().filter(date -> date.getYear() == beforeLastYear).count());

                yearStatistics.add(beforeCount);
                yearStatistics.add(lastCount);
                yearStatistics.add(currentCount);


                //统计当年每个月份的违约数量
                List<LocalDateTime> currentYearRecord = allRecordDateTimes.stream().filter(localDateTime -> localDateTime.getYear() == currentYear).collect(Collectors.toList());


                Map<String, List<LocalDateTime>> monthStaticsMap = currentYearRecord.stream()
                        .collect(Collectors.groupingBy(date -> date.format(DateTimeFormatter.ofPattern("MM"))));

                monthStatistics = fillMonthArray(monthStaticsMap);

             }
        }

        statisticsRes.put("monthStatistics",monthStatistics);
        statisticsRes.put("yearStatistics",yearStatistics);

        return CommonResponse.ok(statisticsRes);
    }

    /**
     * 汇总每个区域中的摄像头数量
     * @return
     */
    @Override
    public CommonResponse cameraStatistics() {

        List<CameraStatisticsDto> statisticsDtos= recordAlarmMapper.cameraStatistics();

        return CommonResponse.ok(statisticsDtos);
    }

    /**
     * 前五违规项
     * @return
     */
    @Override
    public CommonResponse topFiveViolations() {

        List<TopFiveViolationsDto>  topFiveViolationsDtos= recordAlarmService.topFiveViolations();

        return CommonResponse.ok(topFiveViolationsDtos);

    }

    @Override
    public CommonResponse regionalViolation() {
       List<RegionalViolationDto> regionalViolation= recordAlarmService.regionalViolation();

        return CommonResponse.ok(regionalViolation);
    }

    @Override
    public CommonResponse deviceInformation() {

        return null;
    }

    @Override
    public void removeRelationByRegionId(String id) {
        this.remove(new QueryWrapper<RegionManage>().eq("region_id",id));
    }

    @Override
    public String getRegionByCameraId(Integer cameraId) {

        QueryWrapper<RegionManage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("camera_id",cameraId);

        RegionManage regionManage = baseMapper.selectOne(queryWrapper);
        String regionId = regionManage.getRegionId();
        RegionBase regionBase = iRegionBaseService.getById(regionId);

        return regionBase.getRegionName();
    }

    //    public static void main(String[] args) throws IOException {
//        OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
//        String osJson = JSON.toJSONString(operatingSystemMXBean);
////            System.out.println("osJson is " + osJson);
//        JSONObject jsonObject = JSON.parseObject(osJson);
//        double processCpuLoad = jsonObject.getDouble("processCpuLoad") * 100;
//        double systemCpuLoad = jsonObject.getDouble("systemCpuLoad") * 100;
//        Long totalPhysicalMemorySize = jsonObject.getLong("totalPhysicalMemorySize");
//        Long freePhysicalMemorySize = jsonObject.getLong("freePhysicalMemorySize");
//        double totalMemory = 1.0 * totalPhysicalMemorySize / GB;
//        double freeMemory = 1.0 * freePhysicalMemorySize / GB;
//        double memoryUseRatio = 1.0 * (totalPhysicalMemorySize - freePhysicalMemorySize) / totalPhysicalMemorySize * 100;
//
//        StringBuilder result = new StringBuilder();
//        result.append("系统CPU占用率: ")
//                .append(new BigDecimal(systemCpuLoad).setScale(2, RoundingMode.HALF_UP).doubleValue())
//                .append("%，内存占用率：")
//                .append(new BigDecimal(memoryUseRatio).setScale(2, RoundingMode.HALF_UP).doubleValue()
//                        )
//                .append("%，系统总内存：")
//                .append(new BigDecimal(totalMemory).setScale(2, RoundingMode.HALF_UP).doubleValue()
//                        )
//                .append("GB，系统剩余内存：")
//                .append(new BigDecimal(freeMemory).setScale(2, RoundingMode.HALF_UP).doubleValue())
//                .append("GB，该进程占用CPU：")
//                .append(new BigDecimal(processCpuLoad).setScale(2, RoundingMode.HALF_UP).doubleValue())
//                .append("%");
//        System.out.println(result.toString());
//
//        Process process = Runtime.getRuntime().exec("nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader");
//        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//        String line;
//        while ((line = reader.readLine()) != null) {
//            System.out.println("-----------------------");
//            System.out.println(line);
//        }
//
//
//        try {
//            Thread.sleep(500);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//    }

    /**
     * 填充月份數據
     * @param monthMap
     * @return
     */
    private static List<Integer> fillMonthArray(Map<String, List<LocalDateTime>>  monthMap){
        int [] initMonthStatics ={0,0,0,0,0,0,0,0,0,0,0,0};

        monthMap.forEach((key,value)->{
            initMonthStatics[Integer.parseInt(key)-1]=value.size();
        });

        List<Integer> initMonthStaticsList = Arrays.stream(initMonthStatics).boxed().collect(Collectors.toList());
        return initMonthStaticsList;
    }
}
